//
//	ReaderContentPage.m
//	Reader v2.5.6
//
//	Created by Julius Oklamcak on 2011-07-01.
//	Copyright © 2011-2012 Julius Oklamcak. All rights reserved.
//
//	Permission is hereby granted, free of charge, to any person obtaining a copy
//	of this software and associated documentation files (the "Software"), to deal
//	in the Software without restriction, including without limitation the rights to
//	use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
//	of the Software, and to permit persons to whom the Software is furnished to
//	do so, subject to the following conditions:
//
//	The above copyright notice and this permission notice shall be included in all
//	copies or substantial portions of the Software.
//
//	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
//	OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
//	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
//	CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

#import "ReaderConstants.h"
#import "ReaderContentPage.h"
#import "ReaderContentTile.h"
#import "CGPDFDocument.h"
#import "NoteView.h"
#import "PopoverAnnotsController.h"
#import "UIView+GradientBackground.h"


@implementation ReaderContentPage

//#pragma mark Properties

//@synthesize ;

#pragma mark ReaderContentPage class methods

+ (Class)layerClass
{
#ifdef DEBUGX
	NSLog(@"%s", __FUNCTION__);
#endif

	return [ReaderContentTile class];
}

#pragma mark ReaderContentPage PDF link methods

- (void)highlightPageLinks
{
#ifdef DEBUGX
	NSLog(@"%s", __FUNCTION__);
#endif
    
	if (_links.count > 0) // Add highlight views over all links
	{
		for (ReaderDocumentLink *link in _links) // Enumerate the links array
		{
            UIColor *hilite;
            CGPDFArrayRef highlightRGBArray = NULL; 
            
            if (CGPDFDictionaryGetArray(link.dictionary, "C", &highlightRGBArray))
            {       
                CGPDFReal red = 0.0f; 
                CGPDFReal green = 0.0f;
                CGPDFReal blue = 0.0f;
                
                CGPDFArrayGetNumber(highlightRGBArray, 0, &red);
                CGPDFArrayGetNumber(highlightRGBArray, 1, &green);
                CGPDFArrayGetNumber(highlightRGBArray, 2, &blue);
                
                hilite =    [[UIColor alloc] initWithRed:red green:green blue:blue alpha:0.35];
            }else {
                hilite = [[UIColor yellowColor]colorWithAlphaComponent:0.35f];   
            }
            
            if([[link type]isEqualToString:@"I"]){
                CGPDFArrayRef annotationPointsArray = NULL; // Annotation co-ordinates array
                NSMutableArray *annotsLines = [[NSMutableArray alloc]init];    
                if (CGPDFDictionaryGetArray(link.dictionary, "InkList", &annotationPointsArray))
                {
                    NSInteger lines = CGPDFArrayGetCount(annotationPointsArray);
                    CGPDFArrayRef annotationLineArray = NULL; // Annotation co-ordinates array                        
                    for (NSInteger index = 0; index<lines; index++) // Iterate through all lines
                    {
                        if (CGPDFArrayGetArray(annotationPointsArray,index, &annotationLineArray)==true){
                            
                            NSMutableArray *singleLine = [[NSMutableArray alloc]init]; 
                            NSInteger points = CGPDFArrayGetCount(annotationLineArray);
                            for (NSInteger i = 0; i < points; i++)
                            { //Iterate line points
                                CGPDFReal ll_xxxx = 0.0f;
                                CGPDFReal ll_yyyy = 0.0f;                                 
                                CGPDFArrayGetNumber(annotationLineArray, i, &ll_xxxx); 
                                CGPDFArrayGetNumber(annotationLineArray, i+1, &ll_yyyy);
                                switch (_pageAngle) // Page rotation angle (in degrees)
                                {
                                    case 90: // 90 degree page rotation
                                    {
                                        CGPDFReal swap;
                                        swap = ll_yyyy; ll_yyyy = ll_xxxx; ll_xxxx = swap;
                                        break;
                                    }
                                    case 270: // 270 degree page rotation
                                    {
                                        CGPDFReal swap;
                                        swap = ll_yyyy; ll_yyyy = ll_xxxx; ll_xxxx = swap;
                                        ll_xxxx = ((0.0f - ll_xxxx) + _pageWidth);
                                        break;
                                    }
                                    case 0: // 0 degree page rotation
                                    {
                                        ll_yyyy = ((0.0f - ll_yyyy) + _pageHeight);
                                        break;
                                    }
                                }
                                
                                NSInteger xxxx = ll_xxxx;
                                NSInteger yyyy = ll_yyyy;
                              
                                [singleLine addObject:[NSValue valueWithCGPoint:CGPointMake(xxxx,yyyy)]];
                                i++;
                            }
                            [annotsLines addObject:singleLine];
                        }
                    }//for
                    NoteView *highlight = [[NoteView alloc] initWithFrame:link.rect];
                    //converto le coordinate alla subView
                    NSMutableArray *subLines = [[NSMutableArray alloc]init];
                    for (NSMutableArray *linePoints in annotsLines) {
                        NSMutableArray *subPoints = [[NSMutableArray alloc]init];
                        for(NSValue *val in linePoints){
                            CGPoint subPoint = [self convertPoint:[val CGPointValue] toView:highlight];
                            [subPoints addObject:[NSValue valueWithCGPoint:subPoint]];
                        }
                        [subLines addObject:subPoints];
                        [subPoints release];
                    }
                    UIColor *notBackground =  [UIColor colorWithWhite:0.0 alpha:0.0];
                    [highlight setLines:subLines];
                    highlight.autoresizesSubviews = NO;
                    highlight.userInteractionEnabled = NO;
                    highlight.clearsContextBeforeDrawing = NO;
                    highlight.contentMode = UIViewContentModeRedraw;
                    [highlight setNeedsLayout];
                    highlight.autoresizingMask = UIViewAutoresizingNone;
                    highlight.backgroundColor = notBackground; // Color
                    [self addSubview:highlight]; 
                    [highlight release];
                    [annotsLines release];
                    [subLines release];
                }
            }
            
            if([[link type]isEqualToString:@"H"]){
                
                CGPDFArrayRef highlightPointsArray = NULL; 
                if (CGPDFDictionaryGetArray(link.dictionary, "QuadPoints", &highlightPointsArray))
                {
                    NSInteger points = CGPDFArrayGetCount(highlightPointsArray);    
                    if(points>8){//gruppo di evidenziature.
                        NSInteger k = 0;
                        while (k<points) {
                            CGPDFReal llh_x = 0.0f; CGPDFReal llh_y = 0.0f; // PDFRect lower-left X and Y
                            CGPDFReal urh_x = 0.0f; CGPDFReal urh_y = 0.0f; // PDFRect upper-right X and Y
                            
                            CGPDFArrayGetNumber(highlightPointsArray, k+0, &llh_x); // Lower-left X co-ordinate
                            CGPDFArrayGetNumber(highlightPointsArray, k+1, &llh_y); // Lower-left Y co-ordinate
                            
                            CGPDFArrayGetNumber(highlightPointsArray, k+6, &urh_x); // Upper-right X co-ordinate
                            CGPDFArrayGetNumber(highlightPointsArray, k+7, &urh_y); // Upper-right Y co-ordinate
                            
                            if (llh_x > urh_x) { CGPDFReal t = llh_x; llh_x = urh_x; urh_x = t; } // Normalize Xs
                            if (llh_y > urh_y) { CGPDFReal t = llh_y; llh_y = urh_y; urh_y = t; } // Normalize Ys
                            
                            llh_x -= _pageOffsetX; llh_y -= _pageOffsetY; // Offset lower-left co-ordinate
                            urh_x -= _pageOffsetX; urh_y -= _pageOffsetY; // Offset upper-right co-ordinate
                            
                            switch (_pageAngle) // Page rotation angle (in degrees)
                            {
                                case 90: // 90 degree page rotation
                                {
                                    CGPDFReal swap;
                                    swap = llh_y; llh_y = llh_x; llh_x = swap;
                                    swap = urh_y; urh_y = urh_x; urh_x = swap;
                                    break;
                                }
                                    
                                case 270: // 270 degree page rotation
                                {
                                    CGPDFReal swap;
                                    swap = llh_y; llh_y = llh_x; llh_x = swap;
                                    swap = urh_y; urh_y = urh_x; urh_x = swap;
                                    llh_x = ((0.0f - llh_x) + _pageWidth);
                                    urh_x = ((0.0f - urh_x) + _pageWidth);
                                    break;
                                }
                                    
                                case 0: // 0 degree page rotation
                                {
                                    llh_y = ((0.0f - llh_y) + _pageHeight);
                                    urh_y = ((0.0f - urh_y) + _pageHeight);
                                    break;
                                }
                            }
                            NSInteger vrh_x = llh_x; NSInteger vrh_w = (urh_x - llh_x); // Integer X and width
                            NSInteger vrh_y = llh_y; NSInteger vrh_h = (urh_y - llh_y); // Integer Y and height
                            
                            CGRect viewRect = CGRectMake(vrh_x, vrh_y, vrh_w, vrh_h); // View CGRect from PDFRec
                            
                            
                            UIView *highlight = [[UIView alloc] initWithFrame:viewRect];
                            highlight.autoresizesSubviews = NO;
                            highlight.userInteractionEnabled = NO;
                            highlight.clearsContextBeforeDrawing = NO;
                            highlight.contentMode = UIViewContentModeRedraw;                    
                            highlight.autoresizingMask = UIViewAutoresizingNone;
                            highlight.backgroundColor = hilite; // Color
                            [self addSubview:highlight]; 
                            [highlight release];  
                            k = k+8;
                        }//while
                    } else {
                      
                        UIView *highlight = [[UIView alloc] initWithFrame:link.rect];
                        highlight.autoresizesSubviews = NO;
                        highlight.userInteractionEnabled = NO;
                        highlight.clearsContextBeforeDrawing = NO;
                        highlight.contentMode = UIViewContentModeRedraw;                    
                        highlight.autoresizingMask = UIViewAutoresizingNone;
                        highlight.backgroundColor = hilite; // Color
                        [self addSubview:highlight]; 
                        [highlight release];    
                    }
                
                }

            }
            
            if([[link type]isEqualToString:@"T"]){
                UIColor *hilite = [UIColor colorWithPatternImage:[UIImage imageNamed:@"notes.png"]];
                UIView *highlight = [[UIView alloc] initWithFrame:link.rect];
                highlight.autoresizesSubviews = NO;
                highlight.userInteractionEnabled = NO;
                highlight.clearsContextBeforeDrawing = NO;
                highlight.contentMode = UIViewContentModeRedraw;                    
                highlight.autoresizingMask = UIViewAutoresizingNone;
                highlight.backgroundColor = hilite; // Color
               [highlight setContentMode:UIViewContentModeCenter];
                [self addSubview:highlight]; 
                [highlight release];
            }            
        }                  
	}
}


- (ReaderDocumentLink *)linkFromAnnotation:(CGPDFDictionaryRef)annotationDictionary andAnnots:(NSString *)type
{
#ifdef DEBUGX
	NSLog(@"%s", __FUNCTION__);
#endif
    
    
	ReaderDocumentLink *documentLink = nil; // Document link object
    
	CGPDFArrayRef annotationRectArray = NULL; // Annotation co-ordinates array
    
	if (CGPDFDictionaryGetArray(annotationDictionary, "Rect", &annotationRectArray))
	{
		CGPDFReal ll_x = 0.0f; CGPDFReal ll_y = 0.0f; // PDFRect lower-left X and Y
		CGPDFReal ur_x = 0.0f; CGPDFReal ur_y = 0.0f; // PDFRect upper-right X and Y
        
		CGPDFArrayGetNumber(annotationRectArray, 0, &ll_x); // Lower-left X co-ordinate
		CGPDFArrayGetNumber(annotationRectArray, 1, &ll_y); // Lower-left Y co-ordinate
        
		CGPDFArrayGetNumber(annotationRectArray, 2, &ur_x); // Upper-right X co-ordinate
		CGPDFArrayGetNumber(annotationRectArray, 3, &ur_y); // Upper-right Y co-ordinate
        
		if (ll_x > ur_x) { CGPDFReal t = ll_x; ll_x = ur_x; ur_x = t; } // Normalize Xs
		if (ll_y > ur_y) { CGPDFReal t = ll_y; ll_y = ur_y; ur_y = t; } // Normalize Ys
        
		ll_x -= _pageOffsetX; ll_y -= _pageOffsetY; // Offset lower-left co-ordinate
		ur_x -= _pageOffsetX; ur_y -= _pageOffsetY; // Offset upper-right co-ordinate
        
		switch (_pageAngle) // Page rotation angle (in degrees)
		{
			case 90: // 90 degree page rotation
			{
				CGPDFReal swap;
				swap = ll_y; ll_y = ll_x; ll_x = swap;
				swap = ur_y; ur_y = ur_x; ur_x = swap;
				break;
			}
                
			case 270: // 270 degree page rotation
			{
				CGPDFReal swap;
				swap = ll_y; ll_y = ll_x; ll_x = swap;
				swap = ur_y; ur_y = ur_x; ur_x = swap;
				ll_x = ((0.0f - ll_x) + _pageWidth);
				ur_x = ((0.0f - ur_x) + _pageWidth);
				break;
			}
                
			case 0: // 0 degree page rotation
			{
				ll_y = ((0.0f - ll_y) + _pageHeight);
				ur_y = ((0.0f - ur_y) + _pageHeight);
				break;
			}
		}
        
		NSInteger vr_x = ll_x; NSInteger vr_w = (ur_x - ll_x); // Integer X and width
		NSInteger vr_y = ll_y; NSInteger vr_h = (ur_y - ll_y); // Integer Y and height
        
		CGRect viewRect;
        
        if([type isEqualToString:@"T"]){
        
        viewRect = CGRectMake(vr_x, vr_y, vr_w+5, vr_h-5); 
        } else viewRect = CGRectMake(vr_x, vr_y, vr_w, vr_h); 

 
		documentLink = [ReaderDocumentLink withRect:viewRect dictionary:annotationDictionary AnnotsType:type];
	}
    
	return documentLink;
}

- (void)buildAnnotationLinksList
{
#ifdef DEBUGX
	NSLog(@"%s", __FUNCTION__);
#endif

	_links = [NSMutableArray new]; // Links list array

	CGPDFArrayRef pageAnnotations = NULL; // Page annotations array

	CGPDFDictionaryRef pageDictionary = CGPDFPageGetDictionary(_PDFPageRef);

	if (CGPDFDictionaryGetArray(pageDictionary, "Annots", &pageAnnotations) == true)
	{
		NSInteger count = CGPDFArrayGetCount(pageAnnotations); // Number of annotations

		for (NSInteger index = 0; index < count; index++) // Iterate through all annotations
		{
			CGPDFDictionaryRef annotationDictionary = NULL; // PDF annotation dictionary

			if (CGPDFArrayGetDictionary(pageAnnotations, index, &annotationDictionary) == true)
			{
				const char *annotationSubtype = NULL; // PDF annotation subtype string

				if (CGPDFDictionaryGetName(annotationDictionary, "Subtype", &annotationSubtype) == true)
				{
                    
                    //Ci sono annotazione
                    
                    //Evidenziatura
                    
                    if (strcmp(annotationSubtype, "Highlight") == 0)                         
                    {
						ReaderDocumentLink *documentLink = [self linkFromAnnotation:annotationDictionary andAnnots:@"H"];
						if (documentLink != nil) [_links insertObject:documentLink atIndex:0]; // Add link
					}
                    
                    
                    //Note
                    
                    if(strcmp(annotationSubtype, "Text") == 0) {//icona della nota
						ReaderDocumentLink *documentLink = [self linkFromAnnotation:annotationDictionary andAnnots:@"T"];
                        if (documentLink != nil) [_links insertObject:documentLink atIndex:0]; // Add link
                        
                    }
                    
                    
                    if(strcmp(annotationSubtype, "Popup") == 0) {//icona della nota
						ReaderDocumentLink *documentLink = [self linkFromAnnotation:annotationDictionary andAnnots:@"NOTVIEW"];
                        if (documentLink != nil) [_links insertObject:documentLink atIndex:0]; // Add link
                        
                    }
                    
                    
                    
                    //Disegno a mano libera
                    
                    
                    if(strcmp(annotationSubtype, "Ink") == 0){
                        ReaderDocumentLink *documentLink = [self linkFromAnnotation:annotationDictionary andAnnots:@"I"];
                        if (documentLink != nil) [_links insertObject:documentLink atIndex:0]; // Add link
                        
                        
                        CGPDFArrayRef annotationPointsArray = NULL; // Annotation co-ordinates array
                        
                        if (CGPDFDictionaryGetArray(annotationDictionary, "InkList", &annotationPointsArray))
                        {
                                                        
                            CGPDFArrayRef annotationLineArray = NULL; // Annotation co-ordinates array
                            
                            if (CGPDFArrayGetArray(annotationPointsArray,0, &annotationLineArray)==true){

                                                            
                                CGPDFReal ll_xxxx = 0.0f;
                                CGPDFReal ll_yyyy = 0.0f; // PDFRect lower-left X and Y
                                
                                
                                CGPDFArrayGetNumber(annotationLineArray, 0, &ll_xxxx); // Lower-left X co-ordinate
                                CGPDFArrayGetNumber(annotationLineArray, 1, &ll_yyyy); // Lower-left Y co-ordinate                                
                                
                                
                            }
                            
                        }
                    }
                    
                }
    
//					if (strcmp(annotationSubtype, "Link") == 0) // Found annotation subtype of 'Link'
//					{
//						ReaderDocumentLink *documentLink = [self linkFromAnnotation:annotationDictionary];
//
//						if (documentLink != nil) [_links insertObject:documentLink atIndex:0]; // Add link
//					}
//				}
			}
		}

		[self highlightPageLinks]; // For link support debugging
	}
}

- (CGPDFArrayRef)destinationWithName:(const char *)destinationName inDestsTree:(CGPDFDictionaryRef)node
{
#ifdef DEBUGX
	NSLog(@"%s", __FUNCTION__);
#endif

	CGPDFArrayRef destinationArray = NULL;

	CGPDFArrayRef limitsArray = NULL; // Limits array

	if (CGPDFDictionaryGetArray(node, "Limits", &limitsArray) == true)
	{
		CGPDFStringRef lowerLimit = NULL; CGPDFStringRef upperLimit = NULL;

		if (CGPDFArrayGetString(limitsArray, 0, &lowerLimit) == true) // Lower limit
		{
			if (CGPDFArrayGetString(limitsArray, 1, &upperLimit) == true) // Upper limit
			{
				const char *ll = (const char *)CGPDFStringGetBytePtr(lowerLimit); // Lower string
				const char *ul = (const char *)CGPDFStringGetBytePtr(upperLimit); // Upper string

				if ((strcmp(destinationName, ll) < 0) || (strcmp(destinationName, ul) > 0))
				{
					return NULL; // Destination name is outside this node's limits
				}
			}
		}
	}

	CGPDFArrayRef namesArray = NULL; // Names array

	if (CGPDFDictionaryGetArray(node, "Names", &namesArray) == true)
	{
		NSInteger namesCount = CGPDFArrayGetCount(namesArray);

		for (NSInteger index = 0; index < namesCount; index += 2)
		{
			CGPDFStringRef destName; // Destination name string

			if (CGPDFArrayGetString(namesArray, index, &destName) == true)
			{
				const char *dn = (const char *)CGPDFStringGetBytePtr(destName);

				if (strcmp(dn, destinationName) == 0) // Found the destination name
				{
					if (CGPDFArrayGetArray(namesArray, (index + 1), &destinationArray) == false)
					{
						CGPDFDictionaryRef destinationDictionary = NULL; // Destination dictionary

						if (CGPDFArrayGetDictionary(namesArray, (index + 1), &destinationDictionary) == true)
						{
							CGPDFDictionaryGetArray(destinationDictionary, "D", &destinationArray);
						}
					}

					return destinationArray; // Return the destination array
				}
			}
		}
	}

	CGPDFArrayRef kidsArray = NULL; // Kids array

	if (CGPDFDictionaryGetArray(node, "Kids", &kidsArray) == true)
	{
		NSInteger kidsCount = CGPDFArrayGetCount(kidsArray);

		for (NSInteger index = 0; index < kidsCount; index++)
		{
			CGPDFDictionaryRef kidNode = NULL; // Kid node dictionary

			if (CGPDFArrayGetDictionary(kidsArray, index, &kidNode) == true) // Recurse into node
			{
				destinationArray = [self destinationWithName:destinationName inDestsTree:kidNode];

				if (destinationArray != NULL) return destinationArray; // Return destination array
			}
		}
	}

	return NULL;
}

- (id)annotationLinkTarget:(CGPDFDictionaryRef)annotationDictionary
{
#ifdef DEBUGX
	NSLog(@"%s", __FUNCTION__);
#endif

	id linkTarget = nil; // Link target object

	CGPDFStringRef destName = NULL; const char *destString = NULL;

	CGPDFDictionaryRef actionDictionary = NULL; CGPDFArrayRef destArray = NULL;

	if (CGPDFDictionaryGetDictionary(annotationDictionary, "A", &actionDictionary) == true)
	{
		const char *actionType = NULL; // Annotation action type string

		if (CGPDFDictionaryGetName(actionDictionary, "S", &actionType) == true)
		{
			if (strcmp(actionType, "GoTo") == 0) // GoTo action type
			{
				if (CGPDFDictionaryGetArray(actionDictionary, "D", &destArray) == false)
				{
					CGPDFDictionaryGetString(actionDictionary, "D", &destName);
				}
			}
			else // Handle other link action type possibility
			{
				if (strcmp(actionType, "URI") == 0) // URI action type
				{
					CGPDFStringRef uriString = NULL; // Action's URI string

					if (CGPDFDictionaryGetString(actionDictionary, "URI", &uriString) == true)
					{
						const char *uri = (const char *)CGPDFStringGetBytePtr(uriString); // Destination URI string

						linkTarget = [NSURL URLWithString:[NSString stringWithCString:uri encoding:NSASCIIStringEncoding]];
					}
				}
			}
		}
	}
	else // Handle other link target possibilities
	{
		if (CGPDFDictionaryGetArray(annotationDictionary, "Dest", &destArray) == false)
		{
			if (CGPDFDictionaryGetString(annotationDictionary, "Dest", &destName) == false)
			{
				CGPDFDictionaryGetName(annotationDictionary, "Dest", &destString);
			}
		}
	}

	if (destName != NULL) // Handle a destination name
	{
		CGPDFDictionaryRef catalogDictionary = CGPDFDocumentGetCatalog(_PDFDocRef);

		CGPDFDictionaryRef namesDictionary = NULL; // Destination names in the document

		if (CGPDFDictionaryGetDictionary(catalogDictionary, "Names", &namesDictionary) == true)
		{
			CGPDFDictionaryRef destsDictionary = NULL; // Document destinations dictionary

			if (CGPDFDictionaryGetDictionary(namesDictionary, "Dests", &destsDictionary) == true)
			{
				const char *destinationName = (const char *)CGPDFStringGetBytePtr(destName); // Name

				destArray = [self destinationWithName:destinationName inDestsTree:destsDictionary];
			}
		}
	}

	if (destString != NULL) // Handle a destination string
	{
		CGPDFDictionaryRef catalogDictionary = CGPDFDocumentGetCatalog(_PDFDocRef);

		CGPDFDictionaryRef destsDictionary = NULL; // Document destinations dictionary

		if (CGPDFDictionaryGetDictionary(catalogDictionary, "Dests", &destsDictionary) == true)
		{
			CGPDFDictionaryRef targetDictionary = NULL; // Destination target dictionary

			if (CGPDFDictionaryGetDictionary(destsDictionary, destString, &targetDictionary) == true)
			{
				CGPDFDictionaryGetArray(targetDictionary, "D", &destArray);
			}
		}
	}

	if (destArray != NULL) // Handle a destination array
	{
		NSInteger targetPageNumber = 0; // The target page number

		CGPDFDictionaryRef pageDictionaryFromDestArray = NULL; // Target reference

		if (CGPDFArrayGetDictionary(destArray, 0, &pageDictionaryFromDestArray) == true)
		{
			NSInteger pageCount = CGPDFDocumentGetNumberOfPages(_PDFDocRef); // Pages

			for (NSInteger pageNumber = 1; pageNumber <= pageCount; pageNumber++)
			{
				CGPDFPageRef pageRef = CGPDFDocumentGetPage(_PDFDocRef, pageNumber);

				CGPDFDictionaryRef pageDictionaryFromPage = CGPDFPageGetDictionary(pageRef);

				if (pageDictionaryFromPage == pageDictionaryFromDestArray) // Found it
				{
					targetPageNumber = pageNumber; break;
				}
			}
		}
		else // Try page number from array possibility
		{
			CGPDFInteger pageNumber = 0; // Page number in array

			if (CGPDFArrayGetInteger(destArray, 0, &pageNumber) == true)
			{
				targetPageNumber = (pageNumber + 1); // 1-based
			}
		}

		if (targetPageNumber > 0) // We have a target page number
		{
			linkTarget = [NSNumber numberWithInteger:targetPageNumber];
		}
	}

	return linkTarget;
}

- (id)singleTap:(UITapGestureRecognizer *)recognizer
{
#ifdef DEBUGX
	NSLog(@"%s", __FUNCTION__);
#endif
    
	id result = nil; // Tap result object
    
	if (recognizer.state == UIGestureRecognizerStateRecognized)
	{
		if (_links.count > 0) // Process the single tap
		{
			CGPoint point = [recognizer locationInView:self];
            
			for (ReaderDocumentLink *link in _links) // Enumerate links
			{
				if (CGRectContainsPoint(link.rect, point) == true) // Found it
				{
                    //Devo 
                    
                    CGPDFDictionaryRef annotationDictionary = link.dictionary; // PDF annotation dictionary
                    
                    const char *annotationSubtype = NULL; // PDF annotation subtype string
					if (CGPDFDictionaryGetName(annotationDictionary, "Subtype", &annotationSubtype) == true)
                    {
                        if(strcmp(annotationSubtype, "Text") == 0) {//icona della nota
                            NSInteger Aindex = [_links indexOfObject:link];
                            ReaderDocumentLink *parents = [_links objectAtIndex:Aindex-1];                            
                            
                            CGPDFDictionaryRef destinationDictionary = parents.dictionary; // Testo.
                            CGPDFDictionaryRef parent = nil;
                            CGPDFDictionaryGetDictionary(destinationDictionary, "Parent", &parent);
                            CGPDFDictionaryGetName(parent, "Subtype", &annotationSubtype);
                            CGPDFStringRef content = nil;
                            CGPDFStringRef date = nil;
                            
                            CGPDFDictionaryGetString(parent, "Contents", &content);
                            CFStringRef _con = CGPDFStringCopyTextString(content);
                            
                            CGPDFDictionaryGetString(parent, "CreationDate", &date);
                            CFStringRef _dat = CGPDFStringCopyTextString(date);
                            
                            NSString *annots = [NSString stringWithString:(__bridge NSString *)_con];
                            NSString *creaDate = [NSString stringWithString:(__bridge NSString *)_dat];
                            NSString *normalize = ([creaDate substringWithRange:NSMakeRange(2, 14)]);
                            
                            [NSDateFormatter setDefaultFormatterBehavior:NSDateFormatterBehavior10_4];
                            NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
                            [dateFormatter setDateFormat:@"yyyyMMddHHmmss"];
                            NSDate *dateFromString = [[NSDate alloc] init];
                            dateFromString = [dateFormatter dateFromString:normalize];
                            NSString *dateString = [NSDateFormatter localizedStringFromDate:dateFromString
                                                                                  dateStyle:NSDateFormatterShortStyle 
                                                                                  timeStyle:NSDateFormatterShortStyle];
                            UIPopoverController *viewPopover;
                            PopoverAnnotsController *contents = [[PopoverAnnotsController alloc] init];
                            [contents setAnnots:annots];
                            [contents setDate:dateString];
                            
                            viewPopover = [[UIPopoverController alloc] initWithContentViewController:contents];
                            viewPopover.popoverContentSize = CGSizeMake(130., 130.);
                            [viewPopover presentPopoverFromRect:link.rect inView:self permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
                            viewPopover.delegate = self;
                        }}
                    result = [self annotationLinkTarget:link.dictionary]; break;
				}
			}
		}
	}
	return result;
}

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {
    [popoverController release];
}


#pragma mark ReaderContentPage instance methods

- (id)initWithFrame:(CGRect)frame
{
#ifdef DEBUGX
	NSLog(@"%s", __FUNCTION__);
#endif

	id view = nil; // UIView
 
	if (CGRectIsEmpty(frame) == false)
	{
		if ((self = [super initWithFrame:frame]))
		{
			self.autoresizesSubviews = NO;
			self.userInteractionEnabled = NO;
			self.clearsContextBeforeDrawing = NO;
			self.contentMode = UIViewContentModeRedraw;
			self.autoresizingMask = UIViewAutoresizingNone;
			self.backgroundColor = [UIColor clearColor];

			view = self; // Return self
		}
	}
	else // Handle invalid frame size
	{
		[self release];
	}

	return view;
}

- (id)initWithURL:(NSURL *)fileURL page:(NSInteger)page password:(NSString *)phrase
{
#ifdef DEBUGX
	NSLog(@"%s", __FUNCTION__);
#endif

	CGRect viewRect = CGRectZero; // View rect

	if (fileURL != nil) // Check for non-nil file URL
	{
		_PDFDocRef = CGPDFDocumentCreateX((CFURLRef)fileURL, phrase);

		if (_PDFDocRef != NULL) // Check for non-NULL CGPDFDocumentRef
		{
			if (page < 1) page = 1; // Check the lower page bounds

			NSInteger pages = CGPDFDocumentGetNumberOfPages(_PDFDocRef);

			if (page > pages) page = pages; // Check the upper page bounds

			_PDFPageRef = CGPDFDocumentGetPage(_PDFDocRef, page); // Get page

			if (_PDFPageRef != NULL) // Check for non-NULL CGPDFPageRef
			{
				CGPDFPageRetain(_PDFPageRef); // Retain the PDF page

				CGRect cropBoxRect = CGPDFPageGetBoxRect(_PDFPageRef, kCGPDFCropBox);
				CGRect mediaBoxRect = CGPDFPageGetBoxRect(_PDFPageRef, kCGPDFMediaBox);
				CGRect effectiveRect = CGRectIntersection(cropBoxRect, mediaBoxRect);

				_pageAngle = CGPDFPageGetRotationAngle(_PDFPageRef); // Angle

				switch (_pageAngle) // Page rotation angle (in degrees)
				{
					default: // Default case
					case 0: case 180: // 0 and 180 degrees
					{
						_pageWidth = effectiveRect.size.width;
						_pageHeight = effectiveRect.size.height;
						_pageOffsetX = effectiveRect.origin.x;
						_pageOffsetY = effectiveRect.origin.y;
						break;
					}

					case 90: case 270: // 90 and 270 degrees
					{
						_pageWidth = effectiveRect.size.height;
						_pageHeight = effectiveRect.size.width;
						_pageOffsetX = effectiveRect.origin.y;
						_pageOffsetY = effectiveRect.origin.x;
						break;
					}
				}

				NSInteger page_w = _pageWidth; // Integer width
				NSInteger page_h = _pageHeight; // Integer height

				if (page_w % 2) page_w--; if (page_h % 2) page_h--; // Even

				viewRect.size = CGSizeMake(page_w, page_h); // View size
			}
			else // Error out with a diagnostic
			{
				CGPDFDocumentRelease(_PDFDocRef), _PDFDocRef = NULL;

				NSAssert(NO, @"CGPDFPageRef == NULL");
			}
		}
		else // Error out with a diagnostic
		{
			NSAssert(NO, @"CGPDFDocumentRef == NULL");
		}
	}
	else // Error out with a diagnostic
	{
		NSAssert(NO, @"fileURL == nil");
	}

	id view = [self initWithFrame:viewRect]; // UIView setup

	if (view != nil) [self buildAnnotationLinksList]; // Links

	return view;
}

- (void)dealloc
{
#ifdef DEBUGX
	NSLog(@"%s", __FUNCTION__);
#endif

	[_links release], _links = nil;

	@synchronized(self) // Block any other threads
	{
		CGPDFPageRelease(_PDFPageRef), _PDFPageRef = NULL;

		CGPDFDocumentRelease(_PDFDocRef), _PDFDocRef = NULL;
	}

	[super dealloc];
}

#if (READER_DISABLE_RETINA == TRUE) // Option

- (void)didMoveToWindow
{
#ifdef DEBUGX
	NSLog(@"%s", __FUNCTION__);
#endif

	self.contentScaleFactor = 1.0f; // Override scale factor
}

#endif // end of READER_DISABLE_RETINA Option

/*
- (void)layoutSubviews
{
#ifdef DEBUGX
	NSLog(@"%s", __FUNCTION__);
#endif
}
*/

#pragma mark CATiledLayer delegate methods

- (void)drawLayer:(CATiledLayer *)layer inContext:(CGContextRef)context
{
#ifdef DEBUGX
	NSLog(@"%s", __FUNCTION__);
#endif

	CGPDFPageRef drawPDFPageRef = NULL;

	CGPDFDocumentRef drawPDFDocRef = NULL;

	@synchronized(self) // Block any other threads
	{
		drawPDFDocRef = CGPDFDocumentRetain(_PDFDocRef);

		drawPDFPageRef = CGPDFPageRetain(_PDFPageRef);
	}

	//NSLog(@"%s %@", __FUNCTION__, NSStringFromCGRect(CGContextGetClipBoundingBox(context)));

	CGContextSetRGBFillColor(context, 1.0f, 1.0f, 1.0f, 1.0f); // White

	CGContextFillRect(context, CGContextGetClipBoundingBox(context)); // Fill

	if (drawPDFPageRef != NULL) // Go ahead and render the PDF page into the context
	{
		CGContextTranslateCTM(context, 0.0f, self.bounds.size.height); CGContextScaleCTM(context, 1.0f, -1.0f);

		CGContextConcatCTM(context, CGPDFPageGetDrawingTransform(drawPDFPageRef, kCGPDFCropBox, self.bounds, 0, true));

		CGContextSetRenderingIntent(context, kCGRenderingIntentDefault); CGContextSetInterpolationQuality(context, kCGInterpolationDefault);

		CGContextDrawPDFPage(context, drawPDFPageRef); // Render the PDF page into the context
	}

	CGPDFPageRelease(drawPDFPageRef); CGPDFDocumentRelease(drawPDFDocRef); // Cleanup
}

@end

#pragma mark -

//
//	ReaderDocumentLink class implementation
//

@implementation ReaderDocumentLink

#pragma mark Properties

@synthesize rect = _rect;
@synthesize dictionary = _dictionary;
@synthesize type = _type;


#pragma mark ReaderDocumentLink class methods

+ (id)withRect:(CGRect)linkRect dictionary:(CGPDFDictionaryRef)linkDictionary AnnotsType:(NSString *)type
{
#ifdef DEBUGX
	NSLog(@"%s", __FUNCTION__);
#endif
    
	return [[[ReaderDocumentLink alloc] initWithRect:linkRect dictionary:linkDictionary AnnotsType:type] autorelease];
}

#pragma mark ReaderDocumentLink instance methods

- (id)initWithRect:(CGRect)linkRect dictionary:(CGPDFDictionaryRef)linkDictionary AnnotsType:(NSString *)type
{
#ifdef DEBUGX
	NSLog(@"%s", __FUNCTION__);
#endif
    
	if ((self = [super init]))
	{
		_dictionary = linkDictionary;
        
		_rect = linkRect;
        
        _type = type;
	}
    
	return self;
}

- (void)dealloc
{
#ifdef DEBUGX
	NSLog(@"%s", __FUNCTION__);
#endif

	[super dealloc];
}

@end
